package opensocial4gwt;

import com.google.gwt.core.client.JavaScriptObject;

/**
 * A wrapper with methods for interacting with native JavaScript objects and
 * arrays.
 * 
 * @author David Wolverton
 */
public class BaseJsObject extends JavaScriptObject {
	protected BaseJsObject() {
	}

	protected final native void set(String key, Object value) /*-{
		this[key] = value;
	}-*/;

	protected final void set(String key, Long value) {
		if (value == null)
			set(key, null);
		else
			set(key, JsObject.parseJSON(value.toString()));
	}

	protected final void setJSON(String key, String value) {
		set(key, JsObject.parseJSON(value));
	}

	protected final native JsObject getJsObject(String key) /*-{
		return this[key];
	}-*/;

	protected final native Number getNumber(String key) /*-{
		return this[key];
	}-*/;

	protected final native Integer getInt(String key) /*-{
		return this[key];
	}-*/;

	protected final native Double getDouble(String key) /*-{
		return this[key];
	}-*/;

	protected final native Boolean getBoolean(String key) /*-{
		var value = this[key];
		if (value == null)
			return null;
		return value ? true : false;
	}-*/;

	protected final native String getString(String key) /*-{
		if (typeof this[key] == 'string')
			return this[key];
		else if (this[key])
			return this[key].toString();
		else
			return null;
	}-*/;

	protected final Long getLong(String key) {
		String s = getString(key);
		if (s == null)
			return null;
		return new Long(s);
	}

	protected final native JsObject getJsObject(int index) /*-{
		return this[index];
	}-*/;

	protected final native <T> T get(int index) /*-{
		return this[index];
	}-*/;

	protected final native String getString(int index) /*-{
		return String( this[index] );
	}-*/;

	protected final Long getLong(int index) {
		String s = getString(index);
		if (s == null)
			return null;
		return new Long(s);
	}

	protected final native void push(Object value) /*-{
		this.push(value);
	}-*/;

	protected final void push(Long value) {
		if (value == null)
			push(null);
		else
			push(JsObject.parseJSON(value.toString()));
	}

	protected final void pushJSON(String value) {
		push(JsObject.parseJSON(value));
	}

	protected final native int length() /*-{
		return this.length;
	}-*/;

	protected final String[] getKeys() {
		BaseJsObject keys = getKeysJs();
		String[] result = new String[keys.length()];
		for (int i = 0; i < result.length; i++) {
			result[i] = keys.get(i);
		}
		return result;
	}

	protected final native BaseJsObject getKeysJs() /*-{
		var array = [];
		for (key in this) {
			array.push(key);
		}
		return array;
	}-*/;

	public final Object call(String key, Object... args) {
		return JsObject.call(this, getJsObject(key), args);
	}

	public final native void setField(String field, Object value) /*-{
		this.setField(field, value);
	}-*/;

	public final void setField(String field, Long value) {
		if (value == null)
			setField(field, null);
		else
			setField(field, JsObject.parseJSON(value.toString()));
	}

	protected final native JsObject getFieldJsObject(String key) /*-{
		return this.getField(key);
	}-*/;

	protected final native Number getFieldNumber(String key) /*-{
		return this.getField(key);
	}-*/;

	protected final native Integer getFieldInt(String key) /*-{
		return this.getField(key);
	}-*/;

	protected final native Double getFieldDouble(String key) /*-{
		return this.getField(key);
	}-*/;

	protected final native Boolean getFieldBoolean(String key) /*-{
		var value = this.getField(key);
		if (value == null)
			return null;
		return value ? true : false;
	}-*/;

	protected final native String getFieldString(String key) /*-{
		var value = this.getField(key);
		if (typeof value == 'string')
			return value;
		else if (value)
			return value.toString();
		else
			return null;
	}-*/;
}
